﻿using System;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Scoreboard.Model;

namespace Scoreboard.Scripting
{
	public class Helper
	{
		public IEnumerable<Participant> Take(Tournament t, int count)
		{
			return t.Participants.Take(count);
		}

		public IEnumerable<Participant> SkipTake(Tournament t, int skipCount, int takeCount)
		{
			return t.Participants.Skip(skipCount).Take(takeCount);
		}

		public IEnumerable<Participant> Skip(Tournament t, int count)
		{
			return t.Participants.Skip(count);
		}

		public void AddToGroup(Group group, IEnumerable<Participant> participants)
		{
			foreach (var participant in participants)
			{
				group.Participants.Add(participant);
			}
		}

		public IEnumerable<Participant> TakeFromGroup(Group group, int count)
		{
			return group.Table.Take(count).Select(p => p.Copy());
		}

		public object GetItem(IEnumerable collection, int index)
		{
			return collection.OfType<object>().ElementAt(index);
		}

		public void GeneratePlayOff(Tournament tournament)
		{
			var lastStage = tournament.Stages.OrderBy(s => s.IndexNumber).Last();
			var stage = new Stage
			            	{
			            		IndexNumber = lastStage.IndexNumber + 1
			            	};
			
			lastStage.IsFinished = true;
			for (int i = 0; i < lastStage.Groups.Count; i += 2)
			{
				var firstGroup = lastStage.Groups.ElementAt(i);
				var secondGroup = lastStage.Groups.ElementAt(i + 1);

				var group = new Group
				            	{
				            		IndexNumber = i
				            	};
				group.Participants.Add(firstGroup.Table.ElementAt(0).Copy());
				group.Participants.Add(secondGroup.Table.ElementAt(1).Copy());

				var group2 = new Group
				{
					IndexNumber = i + 1
				};
				group2.Participants.Add(secondGroup.Table.ElementAt(0).Copy());
				group2.Participants.Add(firstGroup.Table.ElementAt(1).Copy());

				stage.Groups.Add(group);
				stage.Groups.Add(group2);
			}
			tournament.Stages.Add(stage);
		}

		public void ProceedPlayOff(Tournament tournament)
		{
			var lastStage = tournament.Stages.OrderBy(s => s.IndexNumber).Last();
			var stage = new Stage {IndexNumber = lastStage.IndexNumber + 1};
			var groupsCount = lastStage.Groups.Count;
			if (groupsCount > 2)
			{
				for (int i = 0; i < groupsCount; i+=2)
				{
					var group = new Group
					            	{
					            		IndexNumber = i/2
					            	};
					var firstGroup = lastStage.Groups.ElementAt(i);
					var secondGroup = lastStage.Groups.ElementAt(i + 1);

					group.Participants.Add(firstGroup.Table.First(p => p.IsWinner).Copy());
					group.Participants.Add(secondGroup.Table.First(p => p.IsWinner).Copy());
					stage.Groups.Add(group);
				}
			}
			else
			{
				var firstGroup = lastStage.Groups.ElementAt(0);
				var secondGroup = lastStage.Groups.ElementAt(1);

				var groupFinal = new Group
				{
					IndexNumber = 0
				};

				groupFinal.Participants.Add(firstGroup.Table.First(p => p.IsWinner).Copy());
				groupFinal.Participants.Add(secondGroup.Table.First(p => p.IsWinner).Copy());
				stage.Groups.Add(groupFinal);

				var groupThirdPlace = new Group
				{
					IndexNumber = 1
				};

				groupThirdPlace.Participants.Add(firstGroup.Table.First(p => !p.IsWinner).Copy());
				groupThirdPlace.Participants.Add(secondGroup.Table.First(p => !p.IsWinner).Copy());
				stage.Groups.Add(groupThirdPlace);
			}

			tournament.Stages.Add(stage);
		}

		public void CreateGroups(Tournament tournament, int groupsCount)
		{
			var groups = new List<Group>();
			for (int i = 0; i < groupsCount; i++)
			{
				groups.Add(new Group());
			}
			
			var participants = tournament.Participants.OrderByDescending(p => p.Rating).ToList();
			int currentGroup = 0;
			bool goingDown = true;
			foreach (var participant in participants)
			{
				groups[currentGroup].Participants.Add(participant.Copy());

				if (goingDown)
				{
					if (currentGroup < groups.Count - 1)
					{
						currentGroup++;
					}
					else
					{
						goingDown = false;
					}
				}
				else
				{
					if (currentGroup > 0)
					{
						currentGroup--;
					}
					else
					{
						goingDown = true;
					}
				}
			}

			var orderedGroups = OrderGroups(groups);
			int currentIndexNumber = 0;
			foreach (var group in orderedGroups)
			{
				group.IndexNumber = currentIndexNumber;
				currentIndexNumber++;
			}

			var stage = new Stage();
			foreach (var group in orderedGroups)
			{
				stage.Groups.Add(group);
			}
			tournament.Stages.Add(stage);
		}

		private List<Group> OrderGroups(List<Group> groups)
		{
			if (groups.Count < 3)
			{
				return groups;
			}

			var orderedGroups = new List<Group>();
			var order = new int[0];
			if (groups.Count == 4)
			{
				order = new[] {1, 4, 2, 3};
			}
			else if (groups.Count == 8)
			{
				order = new[] {1, 8, 4, 5, 2, 7, 3, 6};
			}
			else if (groups.Count == 16)
			{
				order = new[] {1, 16, 8, 9, 4, 13, 5, 12, 2, 15, 7, 10, 3, 14, 6, 11};
			}

			foreach (var i in order)
			{
				orderedGroups.Add(groups[i - 1]);
			}

			return orderedGroups;
		}
	}
}
